
modules = typeof(modules) == 'undefined' ? [] : modules;
modules.push(function(Y) {

  this.CssRules = function() {

    var Selector = function(q) {
      this.query = q;
      //console.log('selector for', q);
      var query = q.split(' ');
      var query_len = query.length;
      
      this.matches = function(path) {
        var score = 0;
        path = path.split(" ");
        //console.log('comparing', path.join(" "), query.join(" "));

        var p = path.length -1;
        var q = query_len -1;

        while (p >= 0 && q >= 0) {
          //console.log(p);
          if (path[p] != query[q]) {
            p--;
            //console.log(path[p], '!=', query[q])
            if (p < 0) {
              return false;
            }
          } else {
            //console.log(path[p], '==', query[q])
            score++;
            p--; q--;
          }
        }
        return score;
      }
    }

    var SelectorGroup = function(query) {
      this.query = query;      
      var selectors = [];
      
      this.add = function(selector) {
        selectors.push(selector);
      }
      this.matches = function(path) {
        var maxScore = 0;
        var score;
        for (var s = selectors.length; s > 0; s--) {
          if (score = selectors[s-1].matches(path)) {
            if (score > maxScore) {
              maxScore = score;
            }
          }
        }
        return maxScore;
      }
    }

    var parseSelector = function(selector) {
      //console.log('parse selector', q);
      var queries = selector.split(",");
      if (queries.length > 1) {
        s = new SelectorGroup(selector);
        for(var q = queries.length; q > 0; q--) {
          s.add(new Selector(queries[q-1]));
        }
        return s;
      } else {
        return new Selector(selector);
      }
    }

    var rules = [];
    var ruleIndex = {};

    this.works = true;
    this.setRule = function(selector, options) {
//      console.log('len', rules.length)

      //console.log(rules);
//      console.log('Rule Index', ruleIndex[selector]);
//      console.log(ruleIndex.hasOwnProperty(selector));

      if (ruleIndex.hasOwnProperty(selector)) {
        var index = ruleIndex[selector];
        rules[index][1] = this.mergeRules(rules[index][1], options);
      } else {
        ruleIndex[selector] = rules.length;
        //console.log(rules.length);
        rules.push([parseSelector(selector), options]);
      }
//      console.log('sel', selector);
    }

    this.mergeRules = function(a, b) {
      o = {};
      for (var key in a) {
        if (!b.hasOwnProperty(key)) {
          o[key] = a[key];
        }
      }
      for (var key in b) {
        //console.log(key);
        if (b.hasOwnProperty(key)) {
          if (!b[key].match(/^\s*$/)) {
            o[key] = b[key];
          }
        }
      }
      return o;
    }
    
    this.getRule = function(path) {
      for (var i = rules.length-1; i >= 0; i--) {
        var score = rules[i][0].matches(path);
        if (score > 0) {
          return rules[i][1];
        }
      }
      return {};
    }

    this.getGroups = function(path) {
      return this.matchingGroups(path);
    }

    this.matchingGroups = function(path) {
      var groups = [];
      var score;
      for (var i = rules.length-1; i >= 0; i--) {
        score = rules[i][0].matches(path);
        if (score > 0) {
          groups.push([score, [rules[i][0].query, rules[i][1]]]);
        }
      }
      return groups.sort();
    }

    this.normalizeSelector = function(selector) {
      selector = selector.replace(/^\s*/, "").replace(/\s*$/, "");
      return selector.replace(/\s+/, " ")
    }

    this.loadHash = function(groups) {
      for (var selector in groups) {
        var rules = groups[selector];
        if (Y.Lang.isObject(rules)) {
          this.setRule(selector, rules);
        }
      }
    }
  }

});



